#include "PCFG.h"
#include <cstring>
using namespace std;

void PriorityQueue::CalProb(PT &pt)
{
    // 计算PriorityQueue里面一个PT的流程如下：
    // 1. 首先需要计算一个PT本身的概率。例如，L6S1的概率为0.15
    // 2. 需要注意的是，Queue里面的PT不是"纯粹的"PT，而是除了最后一个segment以外，全部被value实例化的PT
    // 3. 所以，对于L6S1而言，其在Queue里面的实际PT可能是123456S1，其中"123456"为L6的一个具体value。
    // 4. 这个时候就需要计算123456在L6中出现的概率了。假设123456在所有L6 segment中的概率为0.1，那么123456S1的概率就是0.1*0.15

    // 计算一个PT本身的概率。后续所有具体segment value的概率，直接累乘在这个初始概率值上
    pt.prob = pt.preterm_prob;

    // index: 标注当前segment在PT中的位置
    int index = 0;


    for (int idx : pt.curr_indices)
    {
        // pt.content[index].PrintSeg();
        if (pt.content[index].type == 1)
        {
            // 下面这行代码的意义：
            // pt.content[index]：目前需要计算概率的segment
            // m.FindLetter(seg): 找到一个letter segment在模型中的对应下标
            // m.letters[m.FindLetter(seg)]：一个letter segment在模型中对应的所有统计数据
            // m.letters[m.FindLetter(seg)].ordered_values：一个letter segment在模型中，所有value的总数目
            pt.prob *= m.letters[m.FindLetter(pt.content[index])].ordered_freqs[idx];
            pt.prob /= m.letters[m.FindLetter(pt.content[index])].total_freq;
            // cout << m.letters[m.FindLetter(pt.content[index])].ordered_freqs[idx] << endl;
            // cout << m.letters[m.FindLetter(pt.content[index])].total_freq << endl;
        }
        if (pt.content[index].type == 2)
        {
            pt.prob *= m.digits[m.FindDigit(pt.content[index])].ordered_freqs[idx];
            pt.prob /= m.digits[m.FindDigit(pt.content[index])].total_freq;
            // cout << m.digits[m.FindDigit(pt.content[index])].ordered_freqs[idx] << endl;
            // cout << m.digits[m.FindDigit(pt.content[index])].total_freq << endl;
        }
        if (pt.content[index].type == 3)
        {
            pt.prob *= m.symbols[m.FindSymbol(pt.content[index])].ordered_freqs[idx];
            pt.prob /= m.symbols[m.FindSymbol(pt.content[index])].total_freq;
            // cout << m.symbols[m.FindSymbol(pt.content[index])].ordered_freqs[idx] << endl;
            // cout << m.symbols[m.FindSymbol(pt.content[index])].total_freq << endl;
        }
        index += 1;
    }
    // cout << pt.prob << endl;
}

void PriorityQueue::init()
{
    // cout << m.ordered_pts.size() << endl;
    // 用所有可能的PT，按概率降序填满整个优先队列
    for (PT pt : m.ordered_pts)
    {
        for (segment seg : pt.content)
        {
            if (seg.type == 1)
            {
                // 下面这行代码的意义：
                // max_indices用来表示PT中各个segment的可能数目。例如，L6S1中，假设模型统计到了100个L6，那么L6对应的最大下标就是99
                // （但由于后面采用了"<"的比较关系，所以其实max_indices[0]=100）
                // m.FindLetter(seg): 找到一个letter segment在模型中的对应下标
                // m.letters[m.FindLetter(seg)]：一个letter segment在模型中对应的所有统计数据
                // m.letters[m.FindLetter(seg)].ordered_values：一个letter segment在模型中，所有value的总数目
                pt.max_indices.emplace_back(m.letters[m.FindLetter(seg)].ordered_values.size());
            }
            if (seg.type == 2)
            {
                pt.max_indices.emplace_back(m.digits[m.FindDigit(seg)].ordered_values.size());
            }
            if (seg.type == 3)
            {
                pt.max_indices.emplace_back(m.symbols[m.FindSymbol(seg)].ordered_values.size());
            }
        }
        pt.preterm_prob = float(m.preterm_freq[m.FindPT(pt)]) / m.total_preterm;
        // pt.PrintPT();
        // cout << " " << m.preterm_freq[m.FindPT(pt)] << " " << m.total_preterm << " " << pt.preterm_prob << endl;

        // 计算当前pt的概率
        CalProb(pt);
        // 将PT放入优先队列
        priority.emplace_back(pt);
    }
    // cout << "priority size:" << priority.size() << endl;
}

void PriorityQueue::PopNext()
{
    // 对优先队列最前面的PT，首先利用这个PT生成一系列猜测
    //Generate(priority.front());
    //Generate_pthread(priority.front());
    //Generate_omp(priority.front());
    Generate_mpi(priority.front());

    // 然后需要根据即将出队的PT，生成一系列新的PT
    vector<PT> new_pts = priority.front().NewPTs();
    for (PT pt : new_pts)
    {
        // 计算概率
        CalProb(pt);
        // 接下来的这个循环，作用是根据概率，将新的PT插入到优先队列中
        for (auto iter = priority.begin(); iter != priority.end(); iter++)
        {
            // 对于非队首和队尾的特殊情况
            if (iter != priority.end() - 1 && iter != priority.begin())
            {
                // 判定概率
                if (pt.prob <= iter->prob && pt.prob > (iter + 1)->prob)
                {
                    priority.emplace(iter + 1, pt);
                    break;
                }
            }
            if (iter == priority.end() - 1)
            {
                priority.emplace_back(pt);
                break;
            }
            if (iter == priority.begin() && iter->prob < pt.prob)
            {
                priority.emplace(iter, pt);
                break;
            }
        }
    }

    // 现在队首的PT善后工作已经结束，将其出队（删除）
    priority.erase(priority.begin());
}

// 这个函数你就算看不懂，对并行算法的实现影响也不大
// 当然如果你想做一个基于多优先队列的并行算法，可能得稍微看一看了
vector<PT> PT::NewPTs()
{
    // 存储生成的新PT
    vector<PT> res;

    // 假如这个PT只有一个segment
    // 那么这个segment的所有value在出队前就已经被遍历完毕，并作为猜测输出
    // 因此，所有这个PT可能对应的口令猜测已经遍历完成，无需生成新的PT
    if (content.size() == 1)
    {
        return res;
    }
    else
    {
        // 最初的pivot值。我们将更改位置下标大于等于这个pivot值的segment的值（最后一个segment除外），并且一次只更改一个segment
        // 上面这句话里是不是有没看懂的地方？接着往下看你应该会更明白
        int init_pivot = pivot;

        // 开始遍历所有位置值大于等于init_pivot值的segment
        // 注意i < curr_indices.size() - 1，也就是除去了最后一个segment（这个segment的赋值预留给并行环节）
        for (int i = pivot; i < curr_indices.size() - 1; i += 1)
        {
            // curr_indices: 标记各segment目前的value在模型里对应的下标
            curr_indices[i] += 1;

            // max_indices：标记各segment在模型中一共有多少个value
            if (curr_indices[i] < max_indices[i])
            {
                // 更新pivot值
                pivot = i;
                res.emplace_back(*this);
            }

            // 这个步骤对于你理解pivot的作用、新PT生成的过程而言，至关重要
            curr_indices[i] -= 1;
        }
        pivot = init_pivot;
        return res;
    }

    return res;
}

// 这个函数是PCFG并行化算法的主要载体
// 尽量看懂，然后进行并行实现
void PriorityQueue::Generate(PT pt)
{
    // 计算PT的概率，这里主要是给PT的概率进行初始化
    CalProb(pt);

    // 对于只有一个segment的PT，直接遍历生成其中的所有value即可
    if (pt.content.size() == 1)
    {
        // 指向最后一个segment的指针，这个指针实际指向模型中的统计数据
        segment *a;
        // 在模型中定位到这个segment
        if (pt.content[0].type == 1)
        {
            a = &m.letters[m.FindLetter(pt.content[0])];
        }
        if (pt.content[0].type == 2)
        {
            a = &m.digits[m.FindDigit(pt.content[0])];
        }
        if (pt.content[0].type == 3)
        {
            a = &m.symbols[m.FindSymbol(pt.content[0])];
        }
        
        // Multi-thread TODO：
        // 这个for循环就是你需要进行并行化的主要部分了，特别是在多线程&GPU编程任务中
        // 可以看到，这个循环本质上就是把模型中一个segment的所有value，赋值到PT中，形成一系列新的猜测
        // 这个过程是可以高度并行化的
        for (int i = 0; i < pt.max_indices[0]; i += 1)
        {
            string guess = a->ordered_values[i];
            // cout << guess << endl;
            guesses.emplace_back(guess);
            total_guesses += 1;
        }
    }
    else
    {
        string guess;
        int seg_idx = 0;
        // 这个for循环的作用：给当前PT的所有segment赋予实际的值（最后一个segment除外）
        // segment值根据curr_indices中对应的值加以确定
        // 这个for循环你看不懂也没太大问题，并行算法不涉及这里的加速
        for (int idx : pt.curr_indices)
        {
            if (pt.content[seg_idx].type == 1)
            {
                guess += m.letters[m.FindLetter(pt.content[seg_idx])].ordered_values[idx];
            }
            if (pt.content[seg_idx].type == 2)
            {
                guess += m.digits[m.FindDigit(pt.content[seg_idx])].ordered_values[idx];
            }
            if (pt.content[seg_idx].type == 3)
            {
                guess += m.symbols[m.FindSymbol(pt.content[seg_idx])].ordered_values[idx];
            }
            seg_idx += 1;
            if (seg_idx == pt.content.size() - 1)
            {
                break;
            }
        }

        // 指向最后一个segment的指针，这个指针实际指向模型中的统计数据
        segment *a;
        if (pt.content[pt.content.size() - 1].type == 1)
        {
            a = &m.letters[m.FindLetter(pt.content[pt.content.size() - 1])];
        }
        if (pt.content[pt.content.size() - 1].type == 2)
        {
            a = &m.digits[m.FindDigit(pt.content[pt.content.size() - 1])];
        }
        if (pt.content[pt.content.size() - 1].type == 3)
        {
            a = &m.symbols[m.FindSymbol(pt.content[pt.content.size() - 1])];
        }
        
        // Multi-thread TODO：
        // 这个for循环就是你需要进行并行化的主要部分了，特别是在多线程&GPU编程任务中
        // 可以看到，这个循环本质上就是把模型中一个segment的所有value，赋值到PT中，形成一系列新的猜测
        // 这个过程是可以高度并行化的
        for (int i = 0; i < pt.max_indices[pt.content.size() - 1]; i += 1)
        {
            string temp = guess + a->ordered_values[i];
            // cout << temp << endl;
            guesses.emplace_back(temp);
            total_guesses += 1;
        }
    }
}

// 线程工作函数：处理分配的任务段，生成密码猜测
void* thread_worker(void* arg) 
{
    ThreadTask* task = (ThreadTask*)arg;
    const size_t local_size = task->end - task->start;
    vector<string> local_guesses; // 本地存储结果
    local_guesses.reserve(local_size);
    
    const vector<string>& values = task->seg->ordered_values;

    // 批量生成猜测
    if (task->prefix.empty()) {
        // 单segment情况：直接使用segment值作为猜测
        for (size_t i = task->start; i < task->end; ++i) {
            local_guesses.emplace_back(values[i]);
        }
    } else {
        // 多segment情况：需要在前缀后添加最后一个segment的值
        const string& prefix = task->prefix;
        for (size_t i = task->start; i < task->end; ++i) {
            local_guesses.emplace_back(prefix + values[i]);
        }
    }
    
    // 一次性提交结果到共享数据结构，减少锁竞争
    pthread_mutex_lock(task->mutex);
    task->guesses->insert(task->guesses->end(),
                        make_move_iterator(local_guesses.begin()),
                        make_move_iterator(local_guesses.end()));
    *task->total_guesses += local_size;
    pthread_mutex_unlock(task->mutex);
    
    return NULL;
}

void PriorityQueue::Generate_pthread(PT pt)
{
    // 计算总猜测数
    size_t total_size = pt.content.size() == 1 ?
        pt.max_indices[0] :
        pt.max_indices[pt.content.size() - 1];
    
    // 小任务串行处理
    const int MIN_PARALLEL_SIZE = 100000;
    if (total_size < MIN_PARALLEL_SIZE) {
        Generate(pt);
        return;
    }

    // 动态确定线程数
    const int num_threads = min(4, (int)(total_size / 5000));
    if(num_threads < 2) {
        Generate(pt);
        return;
    }

    // 初始化线程、任务和互斥锁
    vector<pthread_t> threads(num_threads);
    vector<ThreadTask> tasks(num_threads);
    pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;

    // 预分配空间
    guesses.reserve(guesses.size() + total_size);

    // 计算每个线程的基本任务和剩余任务
    size_t base_chunk = total_size / num_threads;
    size_t remaining = total_size % num_threads;

    // 计算PT的概率，这里主要是给PT的概率进行初始化
    CalProb(pt);

    // 对于只有一个segment的PT，直接遍历生成其中的所有value即可
    if (pt.content.size() == 1)
    {
        // 指向最后一个segment的指针，这个指针实际指向模型中的统计数据
        segment *a;
        // 在模型中定位到这个segment
        if (pt.content[0].type == 1)
        {
            a = &m.letters[m.FindLetter(pt.content[0])];
        }
        if (pt.content[0].type == 2)
        {
            a = &m.digits[m.FindDigit(pt.content[0])];
        }
        if (pt.content[0].type == 3)
        {
            a = &m.symbols[m.FindSymbol(pt.content[0])];
        }
        
        // 并行化处理第一个循环  
        size_t start = 0;
        for(int i = 0; i < num_threads; i++) {
            size_t chunk_size = base_chunk + (i < remaining ? 1 : 0);
            tasks[i].seg = a;
            tasks[i].start = start;
            tasks[i].end = start + chunk_size;
            tasks[i].prefix = ""; 
            tasks[i].guesses = &guesses;
            tasks[i].total_guesses = &total_guesses;
            tasks[i].mutex = &mutex;
            start += chunk_size;
        }

        // 创建并启动线程
        for(int i = 0; i < num_threads; i++) {
            pthread_create(&threads[i], NULL, thread_worker, &tasks[i]);
        }

        // 等待所有线程完成
        for(int i = 0; i < num_threads; i++) {
            pthread_join(threads[i], NULL);
        }
    }
    else
    {
        string guess;
        int seg_idx = 0;
        // 这个for循环的作用：给当前PT的所有segment赋予实际的值（最后一个segment除外）
        // segment值根据curr_indices中对应的值加以确定
        // 这个for循环你看不懂也没太大问题，并行算法不涉及这里的加速
        for (int idx : pt.curr_indices)
        {
            if (pt.content[seg_idx].type == 1)
            {
                guess += m.letters[m.FindLetter(pt.content[seg_idx])].ordered_values[idx];
            }
            if (pt.content[seg_idx].type == 2)
            {
                guess += m.digits[m.FindDigit(pt.content[seg_idx])].ordered_values[idx];
            }
            if (pt.content[seg_idx].type == 3)
            {
                guess += m.symbols[m.FindSymbol(pt.content[seg_idx])].ordered_values[idx];
            }
            seg_idx += 1;
            if (seg_idx == pt.content.size() - 1)
            {
                break;
            }
        }

        // 指向最后一个segment的指针，这个指针实际指向模型中的统计数据
        segment *a;
        if (pt.content[pt.content.size() - 1].type == 1)
        {
            a = &m.letters[m.FindLetter(pt.content[pt.content.size() - 1])];
        }
        if (pt.content[pt.content.size() - 1].type == 2)
        {
            a = &m.digits[m.FindDigit(pt.content[pt.content.size() - 1])];
        }
        if (pt.content[pt.content.size() - 1].type == 3)
        {
            a = &m.symbols[m.FindSymbol(pt.content[pt.content.size() - 1])];
        }
        
        // 并行化处理第二个循环
        size_t start = 0;
        for(int i = 0; i < num_threads; i++) {
            size_t chunk_size = base_chunk + (i < remaining ? 1 : 0);
            tasks[i].seg = a;
            tasks[i].start = start;
            tasks[i].end = start + chunk_size;
            tasks[i].prefix = guess; 
            tasks[i].guesses = &guesses;
            tasks[i].total_guesses = &total_guesses;
            tasks[i].mutex = &mutex;
            start += chunk_size;
        }

        // 创建并启动线程
        for(int i = 0; i < num_threads; i++) {                  
            pthread_create(&threads[i], NULL, thread_worker, &tasks[i]);
        }
        
        // 等待所有线程完成
        for(int i = 0; i < num_threads; i++) {
            pthread_join(threads[i], NULL);
        }
    }
    // 销毁互斥锁，释放资源
    pthread_mutex_destroy(&mutex);
}

void PriorityQueue::Generate_omp(PT pt)
{
    // 计算总猜测数
    size_t total_size = pt.content.size() == 1 ?
        pt.max_indices[0] :
        pt.max_indices[pt.content.size() - 1];
    
    // 小任务串行处理
    const int MIN_PARALLEL_SIZE = 100000;
    if (total_size < MIN_PARALLEL_SIZE) {
        Generate(pt);
        return;
    }

    // 动态确定线程数
    const int num_threads = min(4, (int)(total_size / 5000));
    if(num_threads < 2) {
        Generate(pt);
        return;
    }

    // 预分配空间
    guesses.reserve(guesses.size() + total_size);

    // 计算PT的概率，这里主要是给PT的概率进行初始化
    CalProb(pt);
    
    // 对于只有一个segment的PT，直接遍历生成其中的所有value即可
    if (pt.content.size() == 1)
    {
        // 指向最后一个segment的指针，这个指针实际指向模型中的统计数据
        segment *a;
        // 在模型中定位到这个segment
        if (pt.content[0].type == 1)
        {
            a = &m.letters[m.FindLetter(pt.content[0])];
        }
        if (pt.content[0].type == 2)
        {
            a = &m.digits[m.FindDigit(pt.content[0])];
        }
        if (pt.content[0].type == 3)
        {
            a = &m.symbols[m.FindSymbol(pt.content[0])];
        }
        
        // 创建OpenMP并行区域，指定线程数
        #pragma omp parallel num_threads(num_threads)
        {
            // 每个线程本地存储结果
            vector<string> local_guesses;
            local_guesses.reserve(total_size / num_threads);
            
            // 生成密码猜测
            #pragma omp for
            for (int i = 0; i < total_size; i++)
            {
                local_guesses.emplace_back(a->ordered_values[i]);
            }
            
            // 将局部结果合并到全局结果中
            #pragma omp critical
            {
                guesses.insert(guesses.end(), 
                            make_move_iterator(local_guesses.begin()),
                            make_move_iterator(local_guesses.end()));
                total_guesses += local_guesses.size();
            }
        }
    }
    else
    {
        string guess;
        int seg_idx = 0;
        // 这个for循环的作用：给当前PT的所有segment赋予实际的值（最后一个segment除外）
        // segment值根据curr_indices中对应的值加以确定
        // 这个for循环你看不懂也没太大问题，并行算法不涉及这里的加速
        for (int idx : pt.curr_indices)
        {
            if (pt.content[seg_idx].type == 1)
            {
                guess += m.letters[m.FindLetter(pt.content[seg_idx])].ordered_values[idx];
            }
            if (pt.content[seg_idx].type == 2)
            {
                guess += m.digits[m.FindDigit(pt.content[seg_idx])].ordered_values[idx];
            }
            if (pt.content[seg_idx].type == 3)
            {
                guess += m.symbols[m.FindSymbol(pt.content[seg_idx])].ordered_values[idx];
            }
            seg_idx += 1;
            if (seg_idx == pt.content.size() - 1)
            {
                break;
            }
        }

        // 指向最后一个segment的指针，这个指针实际指向模型中的统计数据
        segment *a;
        if (pt.content[pt.content.size() - 1].type == 1)
        {
            a = &m.letters[m.FindLetter(pt.content[pt.content.size() - 1])];
        }
        if (pt.content[pt.content.size() - 1].type == 2)
        {
            a = &m.digits[m.FindDigit(pt.content[pt.content.size() - 1])];
        }
        if (pt.content[pt.content.size() - 1].type == 3)
        {
            a = &m.symbols[m.FindSymbol(pt.content[pt.content.size() - 1])];
        }
        
        // 创建OpenMP并行区域，指定线程数
        #pragma omp parallel num_threads(num_threads)
        {
            // 每个线程本地存储结果
            vector<string> local_guesses;
            local_guesses.reserve(total_size / num_threads);
            
            // 生成密码猜测
            #pragma omp for
            for (int i = 0; i < total_size; i++)
            {
                local_guesses.emplace_back(guess + a->ordered_values[i]);
            }
            
            // 将局部结果合并到全局结果中
            #pragma omp critical
            {
                guesses.insert(guesses.end(), 
                            make_move_iterator(local_guesses.begin()),
                            make_move_iterator(local_guesses.end()));
                total_guesses += local_guesses.size();
            }
        }
    }
}

void PriorityQueue::Generate_mpi(PT pt)
{
    // 计算总猜测数
    size_t total_size = pt.content.size() == 1 ? 
        pt.max_indices[0] : 
        pt.max_indices[pt.content.size() - 1];

    // 小任务串行处理
    const int MIN_PARALLEL_SIZE = 200000;
    if (total_size < MIN_PARALLEL_SIZE) {
        Generate(pt);
        return;
    }

    // 动态确定进程数
    const int num_processes = min(4, (int)(total_size / 5000));
    if (num_processes < 2) {
        Generate(pt);
        return;
    }

    int rank, size;
    MPI_Comm_rank(MPI_COMM_WORLD, &rank);  // 获取当前进程的rank
    MPI_Comm_size(MPI_COMM_WORLD, &size);  // 获取总进程数

    // 初始化PT的概率分布
    CalProb(pt);

    // 获取最后一个segment的引用，用于生成猜测
    segment *a;
    if (pt.content.size() == 1) {
        // 单segment情况：直接使用第一个segment
        if (pt.content[0].type == 1) {
            a = &m.letters[m.FindLetter(pt.content[0])];
        } else if (pt.content[0].type == 2) {
            a = &m.digits[m.FindDigit(pt.content[0])];
        } else if (pt.content[0].type == 3) {
            a = &m.symbols[m.FindSymbol(pt.content[0])];
        }
    } else {
        // 多segment情况：构建前缀，使用最后一个segment
        if (pt.content[pt.content.size() - 1].type == 1) {
            a = &m.letters[m.FindLetter(pt.content[pt.content.size() - 1])];
        } else if (pt.content[pt.content.size() - 1].type == 2) {
            a = &m.digits[m.FindDigit(pt.content[pt.content.size() - 1])];
        } else if (pt.content[pt.content.size() - 1].type == 3) {
            a = &m.symbols[m.FindSymbol(pt.content[pt.content.size() - 1])];
        }
    }

    // 计算当前进程负责的数据范围
    int chunk_size = total_size / num_processes;
    int start = rank * chunk_size;
    int end = (rank == num_processes - 1) ? total_size : (rank + 1) * chunk_size;
    int local_size = end - start;

    // 构建前缀字符串（仅多segment情况需要）
    string prefix;
    if (pt.content.size() > 1) {
        int seg_idx = 0;
        for (int idx : pt.curr_indices) {
            if (pt.content[seg_idx].type == 1) {
                prefix += m.letters[m.FindLetter(pt.content[seg_idx])].ordered_values[idx];
            } else if (pt.content[seg_idx].type == 2) {
                prefix += m.digits[m.FindDigit(pt.content[seg_idx])].ordered_values[idx];
            } else if (pt.content[seg_idx].type == 3) {
                prefix += m.symbols[m.FindSymbol(pt.content[seg_idx])].ordered_values[idx];
            }
            seg_idx += 1;
            if (seg_idx == pt.content.size() - 1) break;
        }
    }

    if (rank == 0) {
        // 主进程：处理本地数据并收集其他进程的结果
        guesses.reserve(guesses.size() + total_size);
        
        // 处理主进程自己的部分
        for (int i = start; i < end; i++) {
            guesses.emplace_back(pt.content.size() == 1 ? 
                a->ordered_values[i] : 
                prefix + a->ordered_values[i]);
        }
        total_guesses += local_size;
        
        // 收集其他进程的结果
        for (int i = 1; i < num_processes; i++) {
            // 计算其他进程的数据范围
            int other_start = i * chunk_size;
            int other_end = (i == num_processes - 1) ? total_size : (i + 1) * chunk_size;
            int other_size = other_end - other_start;
            
            // 接收字符串长度数组
            vector<int> lengths(other_size);
            MPI_Recv(lengths.data(), other_size, MPI_INT, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            
            // 计算总字符数
            int total_chars = 0;
            for (int len : lengths) {
                total_chars += len;
            }
            
            // 接收字符串数据
            vector<char> buffer(total_chars);
            MPI_Recv(buffer.data(), total_chars, MPI_CHAR, i, 0, MPI_COMM_WORLD, MPI_STATUS_IGNORE);
            
            // 解析字符串并添加到结果中
            int offset = 0;
            for (int len : lengths) {
                guesses.emplace_back(buffer.data() + offset, len);
                offset += len;
            }
            total_guesses += other_size;
        }
    } else if (rank < num_processes) {
        // 工作进程：处理本地数据并发送给主进程
        vector<string> local_guesses;
        local_guesses.reserve(local_size);
        
        // 生成本地猜测
        for (int i = start; i < end; i++) {
            local_guesses.emplace_back(pt.content.size() == 1 ? 
                a->ordered_values[i] : 
                prefix + a->ordered_values[i]);
        }
        
        // 发送字符串长度数组
        vector<int> lengths(local_guesses.size());
        for (size_t i = 0; i < local_guesses.size(); i++) {
            lengths[i] = local_guesses[i].length();
        }
        MPI_Send(lengths.data(), lengths.size(), MPI_INT, 0, 0, MPI_COMM_WORLD);
        
        // 计算总字符数并发送字符串数据
        int total_chars = 0;
        for (const string& guess : local_guesses) {
            total_chars += guess.length();
        }
        
        vector<char> buffer(total_chars);
        int offset = 0;
        for (const string& guess : local_guesses) {
            memcpy(buffer.data() + offset, guess.c_str(), guess.length());
            offset += guess.length();
        }
        MPI_Send(buffer.data(), total_chars, MPI_CHAR, 0, 0, MPI_COMM_WORLD);
    }

    // 同步所有参与计算的进程
    if (rank < num_processes) {
        MPI_Barrier(MPI_COMM_WORLD);
    }
}